<!--
* @FileDescription: 票号管理
* @Date: 2023年02月01日 17:12:06
* TODO:
* [] Demo
-->
<template>
	<el-row style="height:100%">
		<!-- 左侧表格 -->
		<el-col :span="19" style="height:100%">
			<el-container width="100%" style="height:100%">
				<input
					type="text"
					style="width:100%;padding:5px"
					placeholder="请输入查询条件"
					v-model="searchValue"
				/>
				<div class="tools">
					<div>
						<el-button type="primary" @click="add">新增</el-button>
					</div>
					<div>
						<el-button @click="editTicket">编辑</el-button>
						<el-button @click="importTicket">导入</el-button>
						<el-button @click="exportTicket">导出</el-button>
						<el-button type="danger" @click="deleteTicket">删除</el-button>
					</div>
				</div>
				<el-main>
					<el-table
						:data="ticketList"
						tooltip-effect="dark"
						style="width: 100%"
						@selection-change="handleSelectionChange"
						@cell-click="cellClick"
					>
						<el-table-column type="selection" width="55"> </el-table-column>
						<el-table-column type="index" label="编号"> </el-table-column>
						<el-table-column prop="isDefault" label="是否默认模板">
							<template slot-scope="scope">
								<span>{{ scope.row.isDefault ? '是' : '否' }} </span>
							</template>
						</el-table-column>
						<el-table-column prop="name" label="名称"> </el-table-column>
						<el-table-column prop="createBy" label="创建人"></el-table-column>
						<el-table-column prop="createTime" label="创建时间">
						</el-table-column>
					</el-table>
				</el-main>
				<el-footer>
					<el-pagination
						@size-change="handleSizeChange"
						@current-change="currentChange"
						:current-page="current"
						:page-sizes="[10, 20, 30, 40]"
						:page-size="pageSize"
						layout="total, sizes, prev, pager, next, jumper"
						:total="total"
						style="float:right"
					>
					</el-pagination>
				</el-footer>
			</el-container>
		</el-col>
		<!-- 右侧详细信息 -->
		<el-col :span="5" style="height:100%;overflow:hidden">
			<div style="border:1px solid #000;height:100%;">
				<div class="ticketPreview">票号预览</div>
				<div class="ticketImage">
					<preview :program-data="programData" :visible.sync="previewVisible" />
				</div>
				<div class="applyList">
					<div class="apply">
						应用业务
						<i class="el-icon-plus add-icon" @click="editBizId"></i>
					</div>
					<el-table
						:key="bizKey"
						:data="bizArr"
						border
						style="height:100%;overflow:scroll"
					>
						<el-table-column prop="id" label="编号" width="60">
						</el-table-column>
						<el-table-column prop="name" label="业务名称"> </el-table-column>
					</el-table>
				</div>
			</div>
		</el-col>
		<el-dialog
			:append-to-body="true"
			:visible.sync="open"
			width="30%"
			title="新增票号模板"
		>
			<el-form ref="form" :model="form" label-width="80px">
				<el-form-item label="名称">
					<el-input v-model="form.name"></el-input>
				</el-form-item>
				<el-form-item label="默认模板">
					<el-switch
						v-model="form.isDefault"
						active-color="#13ce66"
						inactive-color="#ff4949"
						:active-value="1"
						:inactive-value="0"
					>
					</el-switch>
				</el-form-item>
				<!-- <el-form-item label="应用业务">
					<el-select v-model="form.bizIds" multiple placeholder="请选择" width="100%">
						<el-option
							v-for="item in deptList"
							:key="item.id"
							:label="item.name"
							:value="item.id"
						>
						</el-option>
					</el-select>
				</el-form-item> -->
			</el-form>
			<div slot="footer" class="dialog-footer">
				<el-button size="small" @click="Cancel">{{
					$t('cancelText')
				}}</el-button>
				<el-button size="small" type="primary" @click="addTicket">{{
					$t('submitText')
				}}</el-button>
			</div>
		</el-dialog>
		<el-dialog
			:append-to-body="true"
			:visible.sync="importDialog"
			width="50%"
			title="导入票号样式"
		>
			<el-form ref="form" :model="form" label-width="100px">
				<el-form-item label="名称">
					<el-input v-model="form.name"></el-input>
				</el-form-item>
			</el-form>
			<el-form ref="form" :model="form" label-width="100px">
				<el-form-item label="上传样式包">
					<el-upload
						class="upload-demo"
						:on-change="handleChange"
						:limit="1"
						:auto-upload="false"
						:file-list="fileList"
					>
						<el-button>选择文件</el-button>
					</el-upload>
				</el-form-item>
			</el-form>
			<div slot="footer" class="dialog-footer">
				<el-button size="small" @click="Cancel">{{
					$t('cancelText')
				}}</el-button>
				<el-button size="small" type="primary" @click="addTicketStyle">{{
					$t('submitText')
				}}</el-button>
			</div>
		</el-dialog>
		<el-dialog
			:append-to-body="true"
			:visible.sync="editBizIdDialog"
			title="编辑票号绑定业务"
		>
			<el-form :mode="form">
				<el-form-item label="应用业务">
					<SelectAll
						v-model="bizIdAr"
						:valueKey="'id'"
						:labelKey="'name'"
						:options="deptList"
					></SelectAll>
				</el-form-item>
				<el-form-item label="默认模板">
					<el-switch
						v-model="form.isDefault"
						active-color="#13ce66"
						inactive-color="#ff4949"
						:active-value="1"
						:inactive-value="0"
						@change="$forceUpdate()"
					>
					</el-switch>
				</el-form-item>
			</el-form>
			<div slot="footer" class="dialog-footer">
				<el-button size="small" @click="() => (editBizIdDialog = false)">{{
					$t('cancelText')
				}}</el-button>
				<el-button size="small" type="primary" @click="confirmeditBizId">{{
					$t('submitText')
				}}</el-button>
			</div>
		</el-dialog>
	</el-row>
</template>
<script>
import SelectAll from '@/components/selectAll'

import dayjs from 'dayjs'
import {
	getTicketStyleList,
	deleteTicketStyle,
	updateTicketStyleList,
	addTicketStyleList,
} from '@/api/qbs/ticketStyle'
import { setKV } from '@/utils/storage-util'
import { deptStatistical } from '@/api/qbs/queueStat'
import { listBizinfo } from '@/api/qbs/bizinfo'
import Preview from '@/views/ips/ticketEditor/preview'
import JSZip from 'jszip'
import FileSaver from 'file-saver'
import { groupTree, addGroup } from '@/api/ips/group'
import { listMaterial, uploadMaterial, addMaterial } from '@/api/ips/material'
import eventbus from '@/utils/eventbus'
export default {
	name: 'ticketManage',
	components: {
		Preview,
		SelectAll,
	},
	// filters:{},
	// mixins:[],
	// props: {},
	data() {
		return {
			deptList: [],
			ticketList: [],
			total: '',
			selectItem: [],
			currentTicketDetails: {},
			pageSize: 10,
			current: 1,
			searchValue: '',
			form: {
				name: '',
				resolution: '600*500',
				type: '0',
				isEditor: 0,
			},
			importForm: {},
			open: false,
			bizArr: [],
			editBizIdDialog: false,
			bizIdAr: [],
			programData: { page: [] },
			importDialog: false,
			fileList: [],
			materialGroupOptions: [],
			oldFile: {},
			formList: [],
			bizKey: 1,
		}
	},
	async created() {
		this.deptStatistical()
		this.getTicketStyleList()
		// 获取素材分组列表
		this.getMaterialGroupTree()
	},
	// computed:{},
	watch: {
		searchValue(val) {
			this.getTicketStyleList({ name: val })
		},
		editBizIdDialog(val) {
			console.log(`val`, val)
			if (!val) {
				this.currentChange(1)
				// this.bizKey++
			}
		},
	},
	// mounted(){},
	methods: {
		// 获取素材分组列表
		getMaterialGroupTree() {
			groupTree({ groupId: 20 }).then((response) => {
				this.materialGroupOptions = response.data
				this.groupDict = []
				const findChildren = (arr, list) => {
					for (let i = 0; i < arr.length; i++) {
						if (arr[i].id) {
							list.push(arr[i])
						}
						if (arr[i].children && arr[i].children.length) {
							findChildren(arr[i].children, list)
						}
					}
				}
				findChildren(this.materialGroupOptions, this.groupDict)
			})
		},
		// 获取科室列表
		async deptStatistical() {
			const { data } = await listBizinfo({ current: 1, size: 1000 })
			this.deptList = data
		},
		async getTicketStyleList(query = {}) {
			const { data, total, pageSize } = await getTicketStyleList(query)
			this.ticketList = data
			this.total = total
			this.pageSize = pageSize
		},
		add() {
			this.open = true
		},
		addTicket() {
			this.open = false
			setTimeout(() => {
				setKV('TICKET_INFO', JSON.stringify(this.form))
				this.$router.push({ name: 'ticketEditor', params: this.form })
			}, 50)
		},
		addTicketStyle() {
			// 判断是否需要创建同名频道
			let isCreateChannel = false
			let layoutComponentList = JSON.parse(this.importForm.layout)[0]
				.componentList
			for (let key in layoutComponentList) {
				if (layoutComponentList[key].type == 'MipsMultiImg') {
					isCreateChannel = true
				}
			}
			// 创建同名节目分组
			let groupId = ''
			if (isCreateChannel == true) {
				let groupObj = {
					name: this.form.name,
					type: 'material',
					parentId: this.materialGroupOptions[0].id,
					isDuplicateName: 'true',
				}
				addGroup(groupObj)
					.then((res) => {
						this.$message({
							message: this.$t('saveSuccess'),
							type: 'success',
							showClose: true,
						})
						// 存储相应的素材
						let formList = this.formList
						for (let index in formList) {
							formList[index].groupId = res.data
							groupId = res.data
							formList[index].groupName = this.importForm.name
							addMaterial(formList[index])
								.then((response) => {
									if (response.code === 0) {
										this.msgSuccess(this.$t('addImageSuccess'))
									}
								})
								.catch(() => {
									this.msgError(response.msg)
								})
						}
					})
					.catch(() => {
						this.$message({
							message: '保存失败',
							type: 'error',
						})
					})
			}
			// 修改json

			this.importDialog = false
			this.importForm.id = null
			this.importForm.name = this.form.name
			// 重置当前创建时间
			this.importForm.createTime = dayjs().format('YYYY-MM-DD HH:mm:ss')
			setTimeout(() => {
				// 同步新素材数据
				// 获取最新数据
				listMaterial({
					current: 1,
					size: 100,
					fullPathId: groupId,
				}).then(async (res) => {
					for (let i in res.data) {
						for (let j in layoutComponentList) {
							let imgSrc = layoutComponentList[j].imgList
								? layoutComponentList[j].imgList[0].imgSrc
								: ''
							if (
								layoutComponentList[j].type == 'MipsMultiImg' &&
								/\/([^/]+).(jpg|jpeg|png|gif|bmp)$/.exec(imgSrc)[1] ==
									res.data[i].name
							) {
								layoutComponentList[j].imgList[0].imgSrc =
									'/pro' + res.data[i].originalUrl
								layoutComponentList[j].imgList[0].imgId = res.data[i].id
							}
						}
					}
					let layout = JSON.parse(this.importForm.layout)
					layout[0].componentList = layoutComponentList
					this.importForm.layout = JSON.stringify(layout)
					if (!this.importForm.id) {
						await addTicketStyleList(this.importForm)
					} else {
						await updateTicketStyleList(this.importForm)
					}

					this.getTicketStyleList()
				})
			}, 500)
		},
		// 上传素材
		uploadFiles(param) {
			const formData = new FormData()
			formData.append('file', param)
			uploadMaterial({
				data: formData,
				headers: { Accept: '*/*', 'Content-Type': 'multipart/form-data' },
			}).then((res) => {
				if (res.code == 0) {
					this.$message({
						message: '上传素材成功',
						type: 'success',
					})
					let _form = {}
					_form.realFileName = res.realFileName
					_form.fileSize = res.fileSize
					_form.type = res.fileType
					_form.format = res.fileFormat
					_form.name = res.fileName
					_form.url = res.path
					// 存储已成功的this.form用于多次save
					this.formList.push(_form)
				} else {
					return this.$message({
						message: '上传素材失败',
						type: 'error',
					})
				}
			})
		},
		handleChange(file) {
			var that = this
			// 创建一个新的 JSZip 实例
			var zip = new JSZip()
			// 使用 JSZip 加载 ZIP 文件
			zip.loadAsync(file.raw).then(function(zip) {
				// 提取并解析 JSON 文件
				var jsonFile = zip.file('data.json')
				if (jsonFile) {
					jsonFile.async('string').then(function(content) {
						// 将文件内容解析为 JSON 对象
						that.importForm = JSON.parse(content)
					})
				} else {
					console.log('JSON file not found in the ZIP archive.')
				}
			})
			this.processZipFile(file.raw)
				.then((imageDataArray) => {
					// 执行上传文件操作，并传递图片数据
					imageDataArray.forEach((imageData) => {
						this.uploadFiles(imageData)
					})
				})
				.catch((error) => {
					console.error('处理压缩包内的图片出错:', error)
				})
		},
		// 处理压缩包内的图片
		processZipFile(file) {
			var that = this
			return new Promise((resolve, reject) => {
				const reader = new FileReader()
				reader.onload = function(event) {
					const zip = new JSZip()
					const imageData = new FormData()

					// 解析压缩包
					zip.loadAsync(event.target.result).then((zip) => {
						const imagePromises = []

						// 遍历压缩包内的文件
						zip.forEach((relativePath, zipEntry) => {
							if (!zipEntry.dir && that.isImageFile(zipEntry.name)) {
								const promise = new Promise((resolveImage) => {
									// 读取图片文件
									zipEntry.async('blob').then((imageBlob) => {
										// 将图片文件添加到 formData
										const imageFile = new File([imageBlob], zipEntry.name)
										imageData.append('file', imageFile)
										resolveImage()
									})
								})
								imagePromises.push(promise)
							}
						})

						// 等待所有图片文件处理完成
						Promise.all(imagePromises).then(() => {
							resolve(imageData)
						})
					})
				}

				reader.onerror = function(event) {
					reject(event.target.error)
				}

				// 读取压缩包文件
				reader.readAsArrayBuffer(file)
			})
		},
		// 判断文件是否为图片文件
		isImageFile(filename) {
			const imageExtensions = ['.jpg', '.jpeg', '.png', '.gif']
			const extension = filename
				.substring(filename.lastIndexOf('.'))
				.toLowerCase()
			return imageExtensions.includes(extension)
		},
		editTicket() {
			if (this.selectItem.length) {
				setTimeout(() => {
					this.$router.push({
						name: 'ticketEditor',
						params: this.selectItem[0],
					})
				}, 50)
			} else {
				this.$message({
					type: 'warning',
					message: '请勾选要编辑的模板',
				})
			}
		},
		importTicket() {
			this.importDialog = true
			this.resetForm()
		},
		exportTicket() {
			if (!this.selectItem.length) {
				return this.$message({
					message: '请选择要导出的模板',
					type: 'warning',
				})
			}
			if (this.selectItem.length > 1) {
				return this.$message({
					message: '请选择单个要导出的模板',
					type: 'warning',
				})
			}
			if (this.selectItem.length == 1) {
				// 创建一个新的 JSZip 实例
				var zip = new JSZip()
				// 将对象的 JSON 字符串转换为 Blob 对象
				var obj = this.selectItem[0]
				// 删除已绑定业务
				obj.bizIds = ''
				var json = JSON.stringify(obj)
				var blob = new Blob([json], { type: 'application/json' })
				var name = obj.name + '.zip'
				// 将 Blob 对象添加到 ZIP 文件中
				zip.file('data.json', blob)
				// 下载图片并添加到 ZIP 文件中
				let layoutComponentList = JSON.parse(obj.layout)[0].componentList
				let promises = [] // 存储图片下载的 Promise
				for (let key in layoutComponentList) {
					if (layoutComponentList[key].type == 'MipsMultiImg') {
						;(function() {
							// 下载并添加图片到ZIP文件
							var imageUrl = JSON.parse(obj.layout)[0].componentList[key]
								.imgList[0].imgSrc // 图片的URL
							var fileName = layoutComponentList[
								key
							].imgList[0].imgSrc.substring(
								layoutComponentList[key].imgList[0].imgSrc.lastIndexOf('/') + 1
							) // 图片的文件名（包括扩展名）
							// 使用 fetch API 下载图片，并将 Promise 存储到数组中
							promises.push(
								fetch(imageUrl)
									.then(function(response) {
										return response.blob()
									})
									.then(function(blob) {
										zip.file(fileName, blob)
									})
									.catch(function(error) {
										console.log('Error downloading image:', error)
									})
							)
						})()
					}
				}
				// 等待所有图片下载完成后生成 ZIP 文件
				Promise.all(promises)
					.then(function() {
						zip.generateAsync({ type: 'blob' }).then(function(content) {
							saveAs(content, name)
						})
					})
					.catch(function(error) {
						console.log('Error downloading images:', error)
					})
			}
		},
		deleteTicket() {
			if (!this.selectItem.length) {
				return this.$message({
					message: '请选择要删除的模板',
					type: 'warning',
				})
			}
			let ids = []
			this.selectItem.forEach((item) => {
				ids.push(item.id)
			})

			this.$confirm('您确定要删除该数据吗？', {
				confirmButtonText: this.$t('submitText'),
				cancelButtonText: this.$t('cancelText'),
				type: 'warning',
			}).then(async () => {
				try {
					await deleteTicketStyle(ids.join(','))
					this.getTicketStyleList()
				} catch (error) {
					this.$message({
						message: error,
						type: 'warning',
					})
				}
			})
		},
		handleSelectionChange(item) {
			this.selectItem = item
			this.currentTicketDetails = item[0]
			// this.cellClick(item[0])
		},
		// 单元格点击时
		cellClick(row) {
			this.programData = row
			let pages = JSON.parse(row.layout)
			this.programData.pages = pages
			this.previewVisible = true
			console.log(`<<<<2023年06月02日 17:02:35>>>>`, this.programData)
			this.bizArr = []
			let bizIdsArr = row.bizIds.split(',')
			this.currentTicketDetails = row
			this.deptList.forEach((item) => {
				let bizIndex = bizIdsArr.findIndex((bizId) => bizId == item.id)
				if (bizIndex > -1) {
					this.bizArr.push({ name: item.name, id: bizIdsArr[bizIndex] })
				}
			})
		},
		// 页码改变时
		handleSizeChange(size) {
			this.pageSize = size
			this.getTicketStyleList({
				size: this.pageSize,
				current: this.current,
			})
		},
		currentChange(size) {
			this.current = size
			this.getTicketStyleList({
				size: this.pageSize,
				current: this.current,
			})
		},
		// 重置表单
		resetForm() {
			// 重置表单
			this.form = {
				name: '',
				resolution: '600*500',
				type: '0',
				isEditor: 0,
			}
			this.fileList = []
		},
		// 取消新增模板
		Cancel() {
			this.open = false
			this.importDialog = false
			this.resetForm()
		},
		// 编辑票号模板绑定的业务ID
		editBizId() {
			this.bizIdAr = []
			if (!this.currentTicketDetails.id) {
				return this.$message({
					type: 'warning',
					message: '请选择票号模板',
				})
			} else {
				this.currentTicketDetails.bizIds.split(',').forEach((item) => {
					item && this.bizIdAr.push(Number(item))
				})
				this.editBizIdDialog = true
				this.form.isDefault = this.currentTicketDetails.isDefault
			}
		},
		// 确认编辑票号模板业务
		async confirmeditBizId() {
			this.currentTicketDetails.bizIds = this.bizIdAr.join(',')
			this.currentTicketDetails.isDefault = this.form.isDefault
			// 更新
			try {
				await updateTicketStyleList(this.currentTicketDetails)
				this.editBizIdDialog = false
				this.resetForm()
				this.bizKey++
				this.$message({
					type: 'success',
					message: '更新成功',
				})
				this.cellClick(this.programData)
				this.deptStatistical()
				this.getTicketStyleList()
			} catch (error) {
				this.bizKey++
			}
		},
	},
}
</script>
<style lang="scss" scoped>
.tools {
	display: flex;
	justify-content: space-between;
	padding: 10px;
}
.apply {
	height: 40px;
	border: 1px solid #ccc;
	display: flex;
	justify-content: space-between;
	align-items: center;
}
.add-icon {
	cursor: pointer;
}
.ticketPreview {
	padding-left: 10px;
	display: flex;
	// border: 1px solid #000;
	align-items: center;
	width: 100%;
	height: 35px;
	background-color: rgb(207, 207, 207);
}
.ticketImage {
	height: 300px;
	overflow: auto;
}
.applyList {
	height: calc(100% - 395px);
	// height: 100%;
	// overflow-y: scroll;
}
</style>
